<!DOCTYPE html>
<html>

<head>
    <title>Animated Particle Constellations</title>
    <style>
        html,
        body {
            width: 100%;
            height: 100%;
            margin: 0;
            overflow: hidden;
        }

        canvas {
            background-color: black;
        }
    </style>
</head>

<body>
    <canvas id="canvas" width="500" height="500"></canvas>
    <script>
        const canvas = document.getElementById('canvas')
        const context = canvas.getContext('2d')
        const particles = []
        const particleSize = 4
        const numParticles = 40
        const distanceThreshold = 100
        const maxLineWidth = 4

        canvas.width = window.innerWidth
        canvas.height = window.innerHeight

        function moveParticle(particle) {
            if (particle.x > canvas.width - particleSize || particle.x < 0) {
                particle.speedX *= -1
            }
            if (particle.y > canvas.height - particleSize || particle.y < 0) {
                particle.speedY *= -1
            }
            particle.x += particle.speedX
            particle.y += particle.speedY
        }

        function drawLine(particle1, particle2) {
            const distanceX = Math.abs(particle1.x - particle2.x)
            const distanceY = Math.abs(particle1.y - particle2.y)
            if (distanceX > distanceThreshold || distanceY > distanceThreshold) {
                return
            }
            const distanceRatio = 1 - ((distanceX + distanceY) / (distanceThreshold * 2))
            context.lineWidth = maxLineWidth * distanceRatio
            context.strokeStyle = `rgba(255, 255, 255, ${distanceRatio})`
            context.beginPath()
            context.moveTo(particle1.x, particle1.y)
            context.lineTo(particle2.x, particle2.y)
            context.stroke()
        }

        function connectWithOtherParticles(particle) {
            for (const otherParticle of particles) {
                if (particle === otherParticle) {
                    continue
                }
                drawLine(particle, otherParticle)
            }
        }

        function drawParticle(particle) {
            context.fillRect(particle.x, particle.y, particleSize, particleSize)
        }

        function clearCanvas() {
            context.clearRect(0, 0, canvas.width, canvas.height)
        }

        function animate() {
            clearCanvas()
            for (const particle of particles) {
                drawParticle(particle)
                connectWithOtherParticles(particle)
                moveParticle(particle)
            }
            window.requestAnimationFrame(animate)
        }

        function initializeParticles() {
            particles.length = 0
            for (let i = 0; i < numParticles; i++) {
                particles.push({
                    x: Math.max(0, Math.random() * canvas.width - particleSize),
                    y: Math.max(0, Math.random() * canvas.height - particleSize),
                    speedX: Math.random() * 2 - 1,
                    speedY: Math.random() * 2 - 1
                })
            }
        }

        context.fillStyle = 'white'
        initializeParticles()
        animate()
    </script>
</body>

</html>